package org.yun.octopus.redis.async;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.yun.octopus.base.core.AsyncHelper;
import org.yun.octopus.base.core.MarkCmd;
import org.yun.octopus.base.util.CommonUtil;
import org.yun.octopus.base.util.SystemTimer;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

import static org.yun.octopus.base.core.RollbackFactory.STEP_RESULT_MAP;
import static org.yun.octopus.base.util.CommonUtil.*;
import static org.yun.octopus.base.util.CommonUtil.objMap2BytesMap;

/**
 * @ProjectName: octopus
 * @ClassName: RedisAsyncMark
 * @Description: 异步队列
 * @Author: liyunfeng31
 * @Date: 2021/1/30 12:16
 */
@Component
public class RedisAsyncMark extends AsyncHelper {

   protected static final Logger LOG = LoggerFactory.getLogger(RedisAsyncMark.class);

   @Resource
   private RedisTemplate<String,Object> redisTemplate;


   /**
    * 批量save
    * @throws InterruptedException ex
    */
   @Override
   public void batchSave() throws InterruptedException {
      List<MarkCmd> cmdList = new ArrayList<>();
      int num = CommonUtil.drain(QUEUE, cmdList, CACHE_SIZE, 1, TimeUnit.SECONDS);
      LOG.info("drain num:{}",num);
      if(CollectionUtils.isEmpty(cmdList)){ return; }

      redisTemplate.executePipelined((RedisCallback<Object>) con -> {
         setVal(cmdList, con);
         return null;
      });
   }



   private void setVal(List<MarkCmd> cmdList, RedisConnection con){

      long time = SystemTimer.currentTime();

      for (MarkCmd cmd : cmdList) {
         String group = cmd.getGroup();
         String bizNo = cmd.getBizNo();
         int code = cmd.getCode();

         byte[] key = (group + "_" + bizNo).getBytes();
         if(code == 0){
            con.del(key);
            continue;
         }

         String childNo = cmd.getChildNo();
         int stepNo = cmd.getStepNo();

         if(con.zAdd(group.getBytes(), time, bizNo.getBytes())){
            con.hMSet(key, stepNo == 0 ? intMap2BytesMap(STEP_RESULT_MAP) : intMap2BytesMap(initMap(stepNo,code)));
            continue;
         }
         if(childNo != null){
            con.hMSet(key, objMap2BytesMap(joinMap(stepNo,code,childNo)));
         }else{
            con.hSet(key, int2Bytes(stepNo), int2Bytes(code));
         }
      }
   }

}

